package com.htpay.controller;

import com.htpay.aspect.AutoLog;
import com.htpay.model.common.DictConstant;
import com.htpay.model.common.ResponseBean;
import com.htpay.model.entity.Merchant;
import com.htpay.model.entity.MerchantOrder;
import com.htpay.model.eo.AlipayReceiveAccount;
import com.htpay.model.eo.ChannelType;
import com.htpay.model.vo.ChargeModel;
import com.htpay.service.IMerchantOrderService;
import com.htpay.service.IMerchantService;
import com.htpay.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 提供上行下发接口api
 * 实现
 */
@Slf4j
@RestController
@RequestMapping("/open")
public class APIController {
    //支付宝转账码支付页面
    private static String ALI_PAY_URL = "/pay_static/aliPayment.html?id=";

    @Autowired
    IMerchantOrderService merchantOrderService;

    @Autowired
    IMerchantService merchantService;

    @AutoLog("上行充值接口")
    @GetMapping(value = "/api/charge")
    public ResponseBean chargeApi(ChargeModel chargeModel, HttpServletRequest req) {
        ResponseBean bean = new ResponseBean();
        try {
            Integer merchantId = chargeModel.getMerchantId();
            if (ObjectConvertUtils.isEmpty(merchantId) || merchantId == 0) {
                return bean.error(-2, "商户ID不能为空");
            }

            String channelType = chargeModel.getChannelType();
            if (ObjectConvertUtils.isEmpty(channelType)) {
                return bean.error(-3, "通道类型不能为空");
            }

            String sign = chargeModel.getSign();
            if (ObjectConvertUtils.isEmpty(sign)) {
                return bean.error(-4, "签名字段不能为空");
            }

            String notifyUrl = chargeModel.getNotifyUrl();
            if (ObjectConvertUtils.isEmpty(notifyUrl)) {
                return bean.error(-5, "商家回调通知url不能为空");
            }

            String outTradeNo = chargeModel.getOutTradeNo();
            if (ObjectConvertUtils.isEmpty(outTradeNo)) {
                return bean.error(-6, "商家交易流水号不能为空");
            }

            String totalMoney = chargeModel.getTotalMoney();
            double rMoney = Double.parseDouble(totalMoney);
            if (ObjectConvertUtils.isEmpty(totalMoney) || rMoney <= 0) {
                return bean.error(-7, "金额不能为空");
            }

            if (rMoney % 100 != 0) {
                return bean.error(-8, "充值金额必须为100的整数倍");
            }

            try {
                Merchant merchant = merchantService.getById(merchantId);

                if (merchant == null) {
                    return bean.error(-9, "非法商家ID");
                }

                //校验签名规则
                Map<String, Object> parameters = new HashMap<String, Object>();
                parameters.put("merchantId", merchantId);
                parameters.put("channelType", channelType);
                parameters.put("notifyUrl", URLEncoder.encode(notifyUrl, "utf-8"));
                parameters.put("outTradeNo", outTradeNo);
                parameters.put("totalMoney", totalMoney);

                String merchantKey = merchant.getMerchantKey();
                String validate_sign = HTPayClientUtil.createSign(parameters, merchantKey);
                log.info("==== 获取到的sign=[" + sign + "], 校验后的validate_sign=[" + validate_sign + "]");
                if (!sign.equals(validate_sign)) {
                    return bean.error(-10, "交易失败，无效的签名");
                }
            } catch (Exception e) {
                log.info("查询商户表失败：" + e.getMessage());
                return bean.error(-11, "交易失败，请联系平台");
            }

            //通过反射方式调用方法
            String methodName = ChannelType.getChannelInfo(channelType).getMethod();
            log.info("==== 通过枚举类获取方法名[" + methodName + "] ====");
            Class[] paramTypes = {ResponseBean.class, ChargeModel.class, HttpServletRequest.class};
            Object[] params = {bean, chargeModel, req};
            Method method = this.getClass().getMethod(methodName, paramTypes);
            //激活
            bean = (ResponseBean) method.invoke(this, params);

            return bean;
        } catch (Exception e) {
            log.info(e.getMessage());
            return bean.error(-999, "操作失败: " + e.getMessage());
        }
    }

    @AutoLog("支付宝消息通知主动回调通知")
    @GetMapping(value = "/api/receive_notify_ap")
    public void receiveNotifyAP(HttpServletRequest req) {
        Map<String, String[]> paramsMap = req.getParameterMap();
        log.info("========== 收到消息通知 =============");
        log.info(paramsMap.keySet().toString());
        log.info(paramsMap.values().toString());

    }

    @AutoLog("查询订单获取转账支付接口")
    @GetMapping(value = "/api/getAliPayment")
    public ResponseBean getPaymentQrCode(MerchantOrder merchantOrder, HttpServletRequest req) {
        ResponseBean bean = new ResponseBean();

        String payId = merchantOrder.getId();
        if (ObjectConvertUtils.isEmpty(payId)) {
            return bean.error("支付ID无效");
        }

        try {
            MerchantOrder mOrder = merchantOrderService.getById(payId);
            if (mOrder == null) {
                return bean.error("交易ID不存在");
            }

            char status = mOrder.getOrderStatus();
            if (status == DictConstant.MERCHANT_ORDER_STATUS_1) {
                return bean.error("该交易订单已支付了");
            }

            boolean flag = MerchantUtil.checkMerchantOrderValidate(mOrder);
            if (flag) {
                //返回字段
                Map<String, String> retMap = new HashMap<String, String>();
                retMap.put("u", mOrder.getAlipayPartnerId());
                retMap.put("o", mOrder.getOrderCode());
                retMap.put("m", mOrder.getRealMoney());
                retMap.put("t", DateUtils.date2Str(mOrder.getCreateTime(), DateUtils.datetimeFormat));
                return bean.success("操作成功!", retMap);
            }

        } catch (Exception e) {
            log.info("获取商户交易订单失败：" + e.getMessage());
            return bean.error("获取交易信息失败");
        }

        return bean.error("该交易已失效，请重新下单!");
    }

    /**
     * 激活alipay h5通道
     *
     * @param bean
     * @param model
     * @return
     */
    public ResponseBean invokeAliPayH5Channel(ResponseBean bean, ChargeModel model, HttpServletRequest req) {
        try {
            String domain = IPUtils.getLocalDomain() + ALI_PAY_URL;
            String outTradeNo = model.getOutTradeNo();
            MerchantOrder merchantOrder = merchantOrderService.queryOrderByMCode(outTradeNo);
            if (merchantOrder != null) {
                log.info("==== 该商户订单号[" + outTradeNo + "]已经存在, 订单ID: [" + merchantOrder.getId() + "] ====");
                char status = merchantOrder.getOrderStatus();
                if (status == DictConstant.MERCHANT_ORDER_STATUS_1) {
                    return bean.error(-12, "该交易订单已支付了");
                }
                boolean flag = MerchantUtil.checkMerchantOrderValidate(merchantOrder);
                if (!flag) return bean.error(-13, "该订单已失效, 请重新下单");
                else {
                    String payUrl = domain + merchantOrder.getId();
                    Map<String, String> retMap = new HashMap<String, String>();
                    retMap.put("pay_url", payUrl);
                    return bean.success("订单已存在且在有效期内", retMap);
                }
            }

            String rmoney = model.getTotalMoney();
            double payMoney = Double.parseDouble(rmoney);
            double realMoney = Double.parseDouble(rmoney);

            String orderNO = MerchantUtil.createOrderSnRandom();
            log.info("==== 生成随机订单号[" + orderNO + "] ====");

            //自动产生转账账户
            AlipayReceiveAccount aact = AlipayReceiveAccount.generateAccount();

            //创建待付款订单
            MerchantOrder mOrder = new MerchantOrder();
            mOrder.setMerchantId(model.getMerchantId());
            mOrder.setOrderCode(orderNO);
            mOrder.setOrderStatus('0'); //未付款
            mOrder.setChargeType(model.getChannelType());
            mOrder.setBankName("支付宝支付");
            mOrder.setMerchantOrderCode(outTradeNo);
            mOrder.setPayMoney(new BigDecimal(payMoney));
            mOrder.setRealMoney(new BigDecimal(realMoney));
            mOrder.setNotifyCount(0);
            mOrder.setNotifyUrl(model.getNotifyUrl());
            mOrder.setCreateTime(new Date());

            //设置当前转账码对应的收款账户
            mOrder.setAlipayPartnerId(aact.getPartnerId());
            mOrder.setPartnerAccount(aact.getPartnerAccount());
            mOrder.setPartnerName(aact.getPartnerName());

            String id = merchantOrderService.insert(mOrder); //保存入库

            Map<String, String> retMap = new HashMap<String, String>();
            String payUrl = domain + id;
            retMap.put("pay_url", payUrl);
            return bean.success("支付通道连接成功", retMap);
        } catch (Exception e) {
            log.info(e.getMessage());
            return bean.error(-1, "很抱歉！支付通道暂时未连接上, 请稍后再重试");
        }
    }

    public void invokeWeChatH5Channel() {
    }

    public void invokeCompleteNotify() {
    }

}
